package org.feng.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.ServletOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;

/**
 * @author  feng
 */
public class PoiUtils {

    public static <T> void exportExcelStream(LinkedHashMap<String, String> params, List<T> data) {
        exportExcelStream(params, data, "表格");
    }

    public static <T> void exportExcelFile(LinkedHashMap<String, String> params, List<T> data, String filePath) {
        File file = FileUtil.file(filePath);
        exportExcelFile(params, data, filePath, FileNameUtil.mainName(file));
    }

    public static <T> void exportExcelStream(LinkedHashMap<String, String> params, List<T> data, String sheetName) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        createSheet(workbook, sheetName, params, data);
        try {
            ServletOutputStream outputStream = HttpUtils.getResponse().getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static <T> void exportExcelFile(LinkedHashMap<String, String> params, List<T> data, String filePath, String sheetName) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        createSheet(workbook, sheetName, params, data);
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(filePath);
            workbook.write(fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    private static <T> void createSheet(XSSFWorkbook workbook, String sheetName, LinkedHashMap<String, String> params, List<T> data) {
        XSSFSheet xssfSheet = workbook.createSheet(sheetName);
        List<String> headerList = new ArrayList<>();
        List<String> filedList = new ArrayList<>();
        makeHeaderAndParamsKey(headerList, filedList, params);
        createExcelHeaderRows(headerList, xssfSheet);
        fillExcelData(data, filedList, xssfSheet);
    }

    private static void makeHeaderAndParamsKey(List<String> headerList, List<String> filedList, LinkedHashMap<String, String> params) {
        Set<Map.Entry<String, String>> set = params.entrySet();
        for (Map.Entry<String, String> entry : set) {
            filedList.add(entry.getKey());
            headerList.add(entry.getValue());
        }
    }

    private static void createExcelHeaderRows(List<String> headerList, XSSFSheet xssfSheet) {
        XSSFRow row = xssfSheet.createRow(0);
        for (int i = 0; i < headerList.size(); i++) {
            XSSFCell cell = row.createCell(i, CellType.STRING);
            cell.setCellValue(headerList.get(i));
        }
    }


    private static <T> void fillExcelData(List<T> data, List<String> filedList, XSSFSheet xssfSheet) {
        JSONArray dataArray = JSONArray.parseArray(JSON.toJSONString(data));
        for (int j = 0; j < dataArray.size(); j++) {
            XSSFRow rows = xssfSheet.createRow(j + 1);
            JSONObject d = JSON.parseObject(JSON.toJSONString(dataArray.get(j)));
            for (int k = 0; k < filedList.size(); k++) {
                XSSFCell cell = rows.createCell(k);
                String s = filedList.get(k);
                cell.setCellValue(d.get(s) == null ? "" : String.valueOf(d.get(s)));
            }
        }
    }
}
